import * as THREE from 'three'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'

/**
 * FBX模型缓存管理器
 */
export class FBXModelCache {
  constructor() {
    this.cache = new Map()
    this.loader = new FBXLoader()
    this.loadingPromises = new Map() // 防止重复加载
    this.maxCacheSize = 100 * 1024 * 1024 // 100MB缓存限制
    this.currentCacheSize = 0
    this.cacheStats = {
      hits: 0,
      misses: 0,
      totalLoaded: 0
    }
  }

  /**
   * 加载模型（带缓存）
   * @param {string} path - 模型路径
   * @param {Object} options - 加载选项
   * @returns {Promise<THREE.Object3D>}
   */
  async loadModel(path, options = {}) {
    const {
      enableCaching = true,
      onProgress = () => {},
      onProcessProgress = () => {}
    } = options

    // 检查缓存
    if (enableCaching && this.cache.has(path)) {
      console.log(`从缓存加载模型: ${path}`)
      this.cacheStats.hits++
      onProgress(100)
      
      const cachedData = this.cache.get(path)
      return this.cloneModel(cachedData.model)
    }

    // 检查是否正在加载
    if (this.loadingPromises.has(path)) {
      console.log(`等待模型加载完成: ${path}`)
      return await this.loadingPromises.get(path)
    }

    // 开始加载
    this.cacheStats.misses++
    const loadPromise = this._loadModelFromFile(path, options)
    this.loadingPromises.set(path, loadPromise)

    try {
      const model = await loadPromise
      
      // 缓存模型
      if (enableCaching) {
        this.cacheModel(path, model)
      }
      
      return model
    } finally {
      this.loadingPromises.delete(path)
    }
  }

  /**
   * 从文件加载模型
   */
  async _loadModelFromFile(path, options) {
    const { onProgress, onProcessProgress } = options

    return new Promise((resolve, reject) => {
      console.log(`开始加载FBX模型: ${path}`)
      
      this.loader.load(
        path,
        async (fbxModel) => {
          console.log('FBX模型加载成功，开始异步处理...')
          
          try {
            // 基础设置
            await this.processModelBasics(fbxModel, onProcessProgress)
            
            this.cacheStats.totalLoaded++
            resolve(fbxModel)
          } catch (error) {
            console.error('模型处理失败:', error)
            reject(error)
          }
        },
        (progress) => {
          if (progress.lengthComputable) {
            const percentage = (progress.loaded / progress.total) * 100
            onProgress(percentage)
          }
        },
        (error) => {
          console.error(`FBX模型加载失败: ${path}`, error)
          reject(error)
        }
      )
    })
  }

  /**
   * 异步处理模型基础设置
   */
  async processModelBasics(model, onProcessProgress = () => {}) {
    const meshes = []
    
    // 收集所有网格
    model.traverse((child) => {
      if (child.isMesh) {
        meshes.push(child)
      }
    })

    const total = meshes.length
    let processed = 0

    // 分批处理，每批5个网格
    const batchSize = 3
    
    for (let i = 0; i < meshes.length; i += batchSize) {
      const batch = meshes.slice(i, i + batchSize)
      
      // 处理当前批次
      for (const mesh of batch) {
        this.processMeshBasics(mesh)
        processed++
        onProcessProgress(Math.round((processed / total) * 100))
      }
      
      // 让出控制权
      await new Promise(resolve => setTimeout(resolve, 0))
    }
  }

  /**
   * 处理网格基础设置
   */
  processMeshBasics(mesh) {
    // 启用阴影
    mesh.castShadow = true
    mesh.receiveShadow = true
    
    // 基础材质处理（快速修复）
    if (mesh.material) {
      const materialsArray = Array.isArray(mesh.material) ? mesh.material : [mesh.material]
      
      materialsArray.forEach((material, index) => {
        // 快速修复黑色材质
        if (material.color && material.color.getHex() === 0x000000) {
          material.color.setHex(0xcccccc)
        }
        
        // 修复透明度
        if (material.opacity !== undefined && material.opacity < 0.1) {
          material.opacity = 1.0
          material.transparent = false
        }
      })
    }
  }

  /**
   * 缓存模型
   */
  cacheModel(path, model) {
    try {
      // 估算模型大小
      const modelSize = this.estimateModelSize(model)
      
      // 检查缓存空间
      if (this.currentCacheSize + modelSize > this.maxCacheSize) {
        this.clearOldCache(modelSize)
      }
      
      const cacheData = {
        model: model.clone(),
        size: modelSize,
        timestamp: Date.now(),
        accessCount: 1
      }
      
      this.cache.set(path, cacheData)
      this.currentCacheSize += modelSize
      
      console.log(`模型已缓存: ${path}, 大小: ${(modelSize / 1024 / 1024).toFixed(2)}MB`)
    } catch (error) {
      console.warn('缓存模型失败:', error)
    }
  }

  /**
   * 克隆模型
   */
  cloneModel(model) {
    const cloned = model.clone()
    
    // 确保材质也被克隆
    cloned.traverse((child) => {
      if (child.isMesh && child.material) {
        if (Array.isArray(child.material)) {
          child.material = child.material.map(mat => mat.clone())
        } else {
          child.material = child.material.clone()
        }
      }
    })
    
    return cloned
  }

  /**
   * 估算模型大小
   */
  estimateModelSize(model) {
    let size = 0
    
    model.traverse((child) => {
      if (child.geometry) {
        // 估算几何体大小
        const attributes = child.geometry.attributes
        for (const name in attributes) {
          size += attributes[name].array.byteLength
        }
        
        if (child.geometry.index) {
          size += child.geometry.index.array.byteLength
        }
      }
      
      if (child.material) {
        // 估算材质贴图大小
        const materials = Array.isArray(child.material) ? child.material : [child.material]
        materials.forEach(material => {
          if (material.map && material.map.image) {
            const img = material.map.image
            size += (img.width * img.height * 4) // 假设RGBA
          }
        })
      }
    })
    
    return size
  }

  /**
   * 清理旧缓存
   */
  clearOldCache(neededSize) {
    const entries = Array.from(this.cache.entries())
    
    // 按访问时间和频率排序
    entries.sort((a, b) => {
      const scoreA = a[1].accessCount / (Date.now() - a[1].timestamp)
      const scoreB = b[1].accessCount / (Date.now() - b[1].timestamp)
      return scoreA - scoreB
    })
    
    let freedSize = 0
    
    for (const [path, data] of entries) {
      if (freedSize >= neededSize) break
      
      this.cache.delete(path)
      freedSize += data.size
      this.currentCacheSize -= data.size
      
      console.log(`清理缓存: ${path}, 释放: ${(data.size / 1024 / 1024).toFixed(2)}MB`)
    }
  }

  /**
   * 预加载模型
   */
  async preloadModel(path) {
    if (this.cache.has(path)) {
      return true
    }
    
    try {
      await this.loadModel(path, { enableCaching: true })
      return true
    } catch (error) {
      console.error(`预加载模型失败: ${path}`, error)
      return false
    }
  }

  /**
   * 清理所有缓存
   */
  clearCache() {
    this.cache.clear()
    this.currentCacheSize = 0
    this.loadingPromises.clear()
    console.log('已清理所有模型缓存')
  }

  /**
   * 获取缓存统计信息
   */
  getCacheStats() {
    return {
      ...this.cacheStats,
      cachedModels: this.cache.size,
      cacheSize: this.currentCacheSize,
      cacheSizeMB: (this.currentCacheSize / 1024 / 1024).toFixed(2),
      hitRate: this.cacheStats.hits / (this.cacheStats.hits + this.cacheStats.misses) * 100
    }
  }

  /**
   * 释放特定模型
   */
  releaseModel(path) {
    if (this.cache.has(path)) {
      const data = this.cache.get(path)
      this.currentCacheSize -= data.size
      this.cache.delete(path)
      console.log(`释放模型缓存: ${path}`)
    }
  }
}

// 创建全局实例
export const fbxModelCache = new FBXModelCache()







